using System;
using System.IO;

namespace ByteFarm.ImageMetaData.Format
{
    public enum ByteOrder
    {
        LittleEndian,
        BigEndian
    }

    public class Reader
    {
        public Reader(ByteOrder byteOrder, BinaryReader reader)
        {
            ByteOrder = byteOrder;
            UnderlyingReader = reader;
        }

        public ByteOrder ByteOrder { get; protected set; }
        public BinaryReader UnderlyingReader { get; protected set; }

        public long Position
        {
            get { return UnderlyingReader.BaseStream.Position; }
        }

        public long Seek(long position)
        {
            return UnderlyingReader.BaseStream.Seek(position, SeekOrigin.Begin);
        }

        public byte ReadByte()
        {
            return UnderlyingReader.ReadByte();
        }

        public sbyte ReadSByte()
        {
            return UnderlyingReader.ReadSByte();
        }

        public char ReadChar()
        {
            return UnderlyingReader.ReadChar();
        }

        public UInt16 ReadUInt16()
        {
            return ByteOrder == ByteOrder.LittleEndian
                       ? ByteEncoder.GetLittleEndian(UnderlyingReader.ReadUInt16())
                       : ByteEncoder.GetBigEndian(UnderlyingReader.ReadUInt16());
        }

        public UInt32 ReadUInt32()
        {
            return ByteOrder == ByteOrder.LittleEndian
                       ? ByteEncoder.GetLittleEndian(UnderlyingReader.ReadUInt32())
                       : ByteEncoder.GetBigEndian(UnderlyingReader.ReadUInt32());
        }

        public Int16 ReadInt16()
        {
            return ByteOrder == ByteOrder.LittleEndian
                       ? ByteEncoder.GetLittleEndian(UnderlyingReader.ReadInt16())
                       : ByteEncoder.GetBigEndian(UnderlyingReader.ReadInt16());
        }

        public Int32 ReadInt32()
        {
            return ByteOrder == ByteOrder.LittleEndian
                       ? ByteEncoder.GetLittleEndian(UnderlyingReader.ReadInt32())
                       : ByteEncoder.GetBigEndian(UnderlyingReader.ReadInt32());
        }

        public float ReadSingle()
        {
            return ByteOrder == ByteOrder.LittleEndian
                       ? ByteEncoder.GetLittleEndian(UnderlyingReader.ReadSingle())
                       : ByteEncoder.GetBigEndian(UnderlyingReader.ReadSingle());
        }

        public Double ReadDouble()
        {
            return ByteOrder == ByteOrder.LittleEndian
                       ? ByteEncoder.GetLittleEndian(UnderlyingReader.ReadDouble())
                       : ByteEncoder.GetBigEndian(UnderlyingReader.ReadDouble());
        }
    }
}